SPB Git forge

spb/immbot-ai

Public
1commits 1branches 0releases
1.5 MBsize
maindefault branch
20 days agolast push
TypeScript 98.3% CSS 0.9% Shell 0.7%
2.4 KB · 55 lines typescript
Raw Blame History
1// Carte des concepts : nœuds (avec maîtrise) + liens typés + compteurs de ressources.2import { NextResponse } from "next/server";3import { apiError, requireEnrollment } from "@/lib/api.ts";4import { requireUser } from "@/lib/auth/session.ts";5import { all } from "@/lib/db/index.ts";6import { masteryForCourse } from "@/lib/learning/mastery.ts";7import { normalizeCourse } from "@/lib/learning/helpers.ts";89export async function GET(_req: Request, ctx: { params: Promise<{ course: string }> }) {10  try {11    const user = await requireUser();12    const course = normalizeCourse((await ctx.params).course);13    requireEnrollment(user.id, course);1415    const mastery = new Map(masteryForCourse(user.id, course).map((m) => [m.conceptId, m]));16    const concepts = all<{ id: number; slug: string; name: string; description: string; week: number | null; importance: number; axis: string }>(17      "SELECT id, slug, name, description, week, importance, axis FROM concepts WHERE course_code = ? ORDER BY week, id",18      course19    );20    const counts = new Map<number, { cards: number; questions: number }>();21    for (const r of all<{ concept_id: number; n: number }>(22      "SELECT concept_id, COUNT(*) as n FROM flashcards WHERE course_code = ? AND concept_id IS NOT NULL GROUP BY concept_id", course23    )) counts.set(r.concept_id, { cards: r.n, questions: 0 });24    for (const r of all<{ concept_id: number; n: number }>(25      "SELECT concept_id, COUNT(*) as n FROM quiz_questions WHERE course_code = ? AND concept_id IS NOT NULL GROUP BY concept_id", course26    )) {27      const e = counts.get(r.concept_id) ?? { cards: 0, questions: 0 };28      e.questions = r.n;29      counts.set(r.concept_id, e);30    }3132    const ids = concepts.map((c) => c.id);33    const links = ids.length34      ? all<{ from_id: number; to_id: number; type: string }>(35          `SELECT from_id, to_id, type FROM concept_links WHERE from_id IN (${ids.map(() => "?").join(",")}) OR to_id IN (${ids.map(() => "?").join(",")})`,36          ...ids, ...ids37        )38      : [];3940    return NextResponse.json({41      nodes: concepts.map((c) => ({42        ...c,43        mastery: mastery.get(c.id)?.score ?? 0,44        level: mastery.get(c.id)?.level ?? "a-decouvrir",45        observations: mastery.get(c.id)?.observations ?? 0,46        cards: counts.get(c.id)?.cards ?? 0,47        questions: counts.get(c.id)?.questions ?? 0,48      })),49      links,50    });51  } catch (e) {52    return apiError(e);53  }54}55